#![allow(dead_code)]
use reqwest::{self, Client, Proxy, RequestBuilder, Response, StatusCode, Method};
use std::time::Duration;
use serde::Serialize;
use std::collections::HashMap;
use thiserror::Error;

/// 自定义错误类型
#[derive(Debug, Error)]
pub enum HttpError {
    #[error("Reqwest error: {0}")]
    Reqwest(#[from] reqwest::Error),

    #[error("HTTP status error: {0} - {1}")]
    Status(StatusCode, String),
}


/// 拦截器上下文
#[derive(Debug, Default, Clone)]
pub struct HttpContext {
    pub headers: HashMap<String, String>,
    // 新增：cookies 为 Option<String>，默认 None（不获取）
    // 当主动初始化为 Some("") 或 Some("自定义值") 时，才会从响应中提取 Cookie
    // let mut need_cookie_ctx = HttpContext {
    //     cookies: Some(String::new()), // 初始化为 Some(...)（即使是空字符串），表示需要获取
    //     ..Default::default()
    // };
    pub cookies: Option<String>,
}

/// 增强版 HTTP 客户端
pub struct HttpClient {
    client: Client,
}

impl HttpClient {
    /// 创建带超时的客户端（不带拦截器）
    pub fn new(timeout_secs: u64) -> Result<Self, reqwest::Error> {
        Ok(Self {
            client: Client::builder()
                .timeout(Duration::from_secs(timeout_secs))
                .build()?,
        })
    }

    /// 创建带代理的客户端（可选是否带拦截器）
    pub fn proxy(
        timeout_secs: u64,
        proxy_url: &str,
        proxy_user: Option<&str>,
        proxy_pass: Option<&str>,
    ) -> Result<Self, reqwest::Error> {
        let mut proxy = Proxy::all(proxy_url)?;

        if let (Some(user), Some(pass)) = (proxy_user, proxy_pass) {
            proxy = proxy.basic_auth(user, pass);
        }

        Ok(Self {
            client: Client::builder()
                .timeout(Duration::from_secs(timeout_secs))
                .proxy(proxy)
                .build()?,
        })
    }

    /// 添加自定义头到请求
    fn apply_headers(
        &self,
        request_builder: RequestBuilder,
        context: &HttpContext,
    ) -> RequestBuilder {
        let mut builder = request_builder;

        // 添加自定义头
        for (key, value) in &context.headers {
            builder = builder.header(key, value);
        }

        builder
    }

    /// 通用请求方法
    pub async fn request(
        &self,
        method: Method,
        url: &str,
        context: Option<HttpContext>,
    ) -> Result<Response, HttpError> {
        let ctx = context.unwrap_or_default();
        let mut request_builder = self.client.request(method.clone(), url);

        // 应用自定义头（无论是否使用拦截器）
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        Ok( response)
    }

    /// GET 请求
    pub async fn get(
        &self,
        url: &str,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let response = self.request(Method::GET, url, context.clone()).await?;
        handle_response(response,context).await
    }

    /// POST JSON 请求
    pub async fn post_json<T: Serialize + ?Sized>(
        &self,
        url: &str,
        body: &T,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.post(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response,Some(ctx)).await
    }

    /// POST Form 请求
    pub async fn post_form(
        &self,
        url: &str,
        form: &[(&str, &str)],
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.post(url).form(form);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response,context).await
    }

    /// POST XML 请求
    pub async fn post_xml(
        &self,
        url: &str,
        xml: &str,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.post(url)
            .header("Content-Type", "application/xml")
            .body(xml.to_owned());

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response,context).await
    }

    /// PUT JSON 请求
    pub async fn put_json<T: Serialize + ?Sized>(
        &self,
        url: &str,
        body: &T,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.put(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response,context).await
    }

    /// DELETE 请求
    pub async fn delete(
        &self,
        url: &str,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let response = self.request(Method::DELETE, url, context.clone()).await?;
        handle_response(response,context).await
    }

    /// PATCH JSON 请求
    pub async fn patch_json<T: Serialize + ?Sized>(
        &self,
        url: &str,
        body: &T,
        context: Option<HttpContext>,
    ) -> Result<String, HttpError> {
        let ctx = context.clone().unwrap_or_default();
        let mut request_builder = self.client.patch(url).json(body);

        // 应用自定义头
        request_builder = self.apply_headers(request_builder, &ctx);

        // 发送请求
        let response = request_builder.send().await?;

        handle_response(response,context).await
    }

    /// 获取响应对象（用于需要处理头信息等场景）
    pub async fn get_response(
        &self,
        url: &str,
        context: Option<HttpContext>,
    ) -> Result<Response, HttpError> {
        self.request(Method::GET, url, context).await
    }

    /// 获取 JSON 响应
    pub async fn get_json<T: serde::de::DeserializeOwned>(
        &self,
        url: &str,
        context: Option<HttpContext>,
    ) -> Result<T, HttpError> {
        let response = self.request(Method::GET, url, context).await?;
        response.json().await.map_err(Into::into)
    }

    /// 添加自定义头到上下文
    pub fn add_custom_header(
        context: &mut HttpContext,
        key: &str,
        value: &str,
    ) {
        context.headers.insert(key.to_string(), value.to_string());
    }

    /// 添加 Cookie 到上下文
    pub fn add_cookie(
        context: &mut HttpContext,
        cookie: &str,
    ) {
        context.headers.insert("Cookie".to_string(), cookie.to_string());
    }

    /// 解析响应中的 Cookie（工具方法）
    pub fn get_cookies(response: &Response) -> HashMap<String, String> {
        let mut cookies = HashMap::new();

        for cookie in response.cookies() {
            cookies.insert(cookie.name().to_string(), cookie.value().to_string());
        }

        cookies
    }
}

pub fn parse_cookie(cookie_str: &str) -> HashMap<String, String> {
    let mut result = HashMap::new();

    // 按分号分割 Cookie 字符串
    for part in cookie_str.split(';') {
        let part = part.trim();
        if part.is_empty() {
            continue; // 跳过空值
        }

        // 查找第一个等号位置
        if let Some(sep_pos) = part.find('=') {
            let key = part[..sep_pos].trim().to_string();
            let value = part[sep_pos + 1..].trim().to_string();

            // 检查是否为需要忽略的 Cookie 属性（如 expires, path 等）
            // 常见的 Cookie 属性列表（小写）
            let ignored_attrs = vec![
                "expires", "path", "domain", "max-age",
                "secure", "httponly", "samesite"
            ];

            if !ignored_attrs.contains(&key.to_lowercase().as_str()) {
                result.insert(key, value);
            }
        }
    }

    result
}

/// 处理响应
async fn handle_response(response: Response,ctx: Option<HttpContext>) -> Result<String, HttpError> {
    let status = response.status();

    // 如果传入了 context 且 cookies 字段为 Some，则提取响应 Cookie
    let mut updated_ctx = ctx;
    if let Some(ref mut context) = updated_ctx {
        if context.cookies.is_some() {
            let cookies_str: String = response
                .cookies()
                .map(|cookie| format!("{}={}", cookie.name(), cookie.value()))
                .collect::<Vec<_>>()
                .join("; ");

            context.cookies = Some(cookies_str);
        }
    }

    let text = response.text().await?;

    if status.is_success() {
        Ok(text)
    } else {
        Err(HttpError::Status(status, text))
    }
}

pub async fn test_http_client() -> Result<(), HttpError> {
    // 创建不带拦截器的客户端
    let client = HttpClient::new(10)?;

    // 使用带拦截器的客户端发送请求
    let mut context = HttpContext::default();
    //2. 主动初始化 cookies 字段，触发获取 Cookie
    // let mut need_cookie_ctx = HttpContext {
    //     cookies: Some(String::new()), // 初始化为 Some(...)（即使是空字符串），表示需要获取
    //     ..Default::default()
    // };
    // // 从 context 中获取响应 Cookie（字符串格式）
    // if let Some(cookies_str) = &need_cookie_ctx.cookies {
    //     println!("获取到的 Cookie: {}", cookies_str);
    //     // 输出示例：session_id=abc123; user_token=xyz789
    // }

    // 添加自定义头
    HttpClient::add_custom_header(&mut context, "X-Custom-Header", "value");

    // 添加完整 Cookie 字符串
    HttpClient::add_cookie(&mut context, "session_id=abc123; user_token=xyz789");

    // 使用 get_response 获取完整响应对象
    match client.get_response("https://api.example.com/data", Some(context)).await {
        Ok(response) => {
            // 解析 cookies
            let cookies = HttpClient::get_cookies(&response);
            println!("Session cookie: {:?}", cookies.get("session_id"));

            // 获取响应文本
            let text = response.text().await?;
            println!("Response: {}", text);
        }
        Err(e) => match e {
            HttpError::Reqwest(err) => eprintln!("Request error: {}", err),
            HttpError::Status(code, msg) => eprintln!("Status error: {} - {}", code, msg),
        },
    }

    match client.post_json(
        "https://api.example.com/post",
        &serde_json::json!({"key": "value"}),
        Some(HttpContext::default())
    ).await {
        Ok(response) => println!("Response: {}", response),
        Err(e) => eprintln!("Error: {:?}", e),
    }

    Ok(())
}